/* Copyright (c) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var orkutdevbox = {};

// Name and version of the application
orkutdevbox.APP_VERSION = "v0.1 BETA";

// Name of the tabs that we show
orkutdevbox.TABS = [ "code", "interface", "console", "samples" ];

// The code output by calls to 'debug.say'
orkutdevbox.output = [];

// Returns the indicated HTML element
orkutdevbox.getEl = function(id) {
   var d = document.getElementById(id);
   if (d == null || typeof d == 'undefined')
      alert("Fatal error: element not found: " + id);
   return d;
};

// Activates the given tab
orkutdevbox.goToTab = function(tabName) {
   var tabIndex = -1;
   for (var i in orkutdevbox.TABS) {
      if (orkutdevbox.TABS[i] == tabName) {
         tabIndex = i;
         break;
      }
   }

   if (tabIndex < 0) {
      orkutdevbox.say("BUG: invalid tab '" + tabName + "'");
      return;
   }

   for (var i = 0; i < orkutdevbox.TABS.length; i++) { 
      orkutdevbox.getEl(orkutdevbox.TABS[i] + "tab").style.display =
         (i == tabIndex) ? '' : 'none';
      orkutdevbox.getEl("tabbutton_" + orkutdevbox.TABS[i]).className =
         (i == tabIndex) ?  'tabbutton_on' : 'tabbutton_off';
   }
};

// Clears the console box and the output[] array
orkutdevbox.clearConsole = function() {
   orkutdevbox.output = [];
   orkutdevbox.getEl("consolebox").value = '';
};

// Given an HTML, extracts the Javascript code embedded in its (one) <script> tag.
// Multiple <script> tags are not yet supported. On failure, returns
// { success: false, message: "(the error message)" }
// On success, returns
// { success: true, html: "html here", script: "script here" }
orkutdevbox.extractJavascript = function(html) {
   var script_tag_start = html.indexOf("<script");
   if (script_tag_start < 0)
      return { success: true, script: "", html: html };

   var i = html.substring(script_tag_start).indexOf('>');
   if (i < 0) 
      return { 
         success: false,
         message: "Bad syntax: your script tag is missing a closing bracket."
      }

   var script_start = script_tag_start + i + 1;

   // look for a closing tag
   i = html.substring(script_start).indexOf("</scri" + "pt>");
   if (i < 0) 
      return { success: false,
            message: "Bad syntax: no closing script tag." };

   var script_end = script_start + i;

   // separate the script from the HTML
   var script = html.substring(script_start, script_end);
   html = html.substring(0, script_tag_start) + 
          html.substring(script_end + 9);

   if (html.indexOf("<script") >= 0) 
      return { success: false,
               message: "Your document has more than one script tag. " +
                        "That's not supported."};

   return { success: true, script: script, html: html };
};

// "Runs" the given HTML code, that is, puts it into the 'Interface' tab,
// extracts the javascript and runs it.
orkutdevbox.runHTML = function(html) {
   orkutdevbox.say("Extracting Javascript from HTML...");
   r = orkutdevbox.extractJavascript(html);

   if (!r.success) {
      orkutdevbox.say("*** Error extracting javascript:");
      orkutdevbox.say("*** " + r.message);
      return false;
   }

   if (r.script == "")
      orkutdevbox.say("WARNING: no Javascript found. Is that right??");

   // load the HTML into the tab
   orkutdevbox.say("Setting up HTML...");
   orkutdevbox.getEl('interfacetab').innerHTML = r.html;

   // and execute the Javascript
   orkutdevbox.say("Running your javascript...");
   try {
      eval(r.script);
   }
   catch (e) {
      orkutdevbox.say("\n\nERROR running script: " + e);
   }

   orkutdevbox.say("Done running your javascript.");
};

// Run the code in the 'code' box as an HTML interface + JS code
orkutdevbox.runAsHTML = function() {
   orkutdevbox.say("Parsing as a plain HTML with Javascript...");
   var html = orkutdevbox.getEl("codebox").value;
   return orkutdevbox.runHTML(html);
};

// Runs the code in the 'code' box as Javascript code
orkutdevbox.runAsJavascript = function() {
   try {
      eval(orkutdevbox.getEl("codebox").value);
      return true;
   }
   catch (e) {
      orkutdevbox.say("\n\n-----\nERROR RUNNING CODE: " + e);
      return false;
   }
};

// Given the text c, determines whether it's a gadget, an HTML file or
// plain Javascript code.
orkutdevbox.detectType = function(c) {
   if (c.indexOf("<?xml ") == 0) return 'gadget';
   else if (c.indexOf("<script") >= 0 && c.indexOf('</sc' + 'ript>') >= 0)
      return 'html';
   else return 'javascript';
};

// Executes the code in the code tab (detects its type and does what's appropriate
// to execute it)
orkutdevbox.runCode = function() {
   var c = orkutdevbox.getEl("codebox").value;
   var type = orkutdevbox.detectType(c);
   orkutdevbox.clearConsole();
   orkutdevbox.say("Running code. Detected type: " + type);

   if (type == 'gadget') {
      orkutdevbox.say("*** Your code is an XML. We don't support that. ");
      orkutdevbox.say("*** Please write only the HTML portion.");
      orkutdevbox.goToTab('console');
   }
   else if (type == 'html') {
      orkutdevbox.goToTab('interface');
      orkutdevbox.runHTML(c);
   }
   else {
      orkutdevbox.goToTab('console');
      orkutdevbox.runAsJavascript();
   }
};

// Prints a debug message to the Output tab.
orkutdevbox.say = function(s) {
   orkutdevbox.output.push(s);
   orkutdevbox.getEl('consolebox').value = orkutdevbox.output.join('\n');

   // try to log to the browser's console, if that's possible
   if (console && console.log) {
      console.log(s);
   }
};

// Function that runs when the application loads -- populates the required
// tabs, etc.
orkutdevbox.onLoad = function() {
   orkutdevbox.goToTab('code');
   orkutdevbox.populateSnippets();
   orkutdevbox.populateSamples();

   // replace gadgets.util.registerOnLoadHandler with our version which
   // simply executes the function directly after a timeout
   gadgets.util.registerOnLoadHandler = function(handler) {
      orkutdevbox.say("Intercepted: registering an onload handler.");
      setTimeout(handler, 500);
   };
};

// Populate the snippets box from the SNIPPETS[] array
orkutdevbox.populateSnippets = function() {
   var html = [];
   for (var i = 0; i < orkutdevbox.SNIPPETS.length; i++) {
      var s = orkutdevbox.SNIPPETS[i];

      if (s.section) {
         html.push("<h2 class='snippetsection'>" + s.section + "</h2>");
         continue;
      }

      html.push("<a class='snippetitem' href='javascript:void(0)'");
      html.push("onclick='window.orkutdevbox.insertSnippet(" + i + ")'");
      html.push("onmouseover='window.orkutdevbox.previewSnippet("+ i + ")'");
      html.push("onmouseout='window.orkutdevbox.previewSnippet(-1)'");
      html.push(">");
      html.push(orkutdevbox.SNIPPETS[i].name);
      html.push("</a>");
   }
   orkutdevbox.getEl('snippetsbox').innerHTML = html.join('');
};

// Populate the samples tab from the SAMPLES[] array
orkutdevbox.populateSamples = function() {
   var html = [ "<ul>" ];
   for (var i = 0; i < orkutdevbox.SAMPLES.length; i++) {
      var s = orkutdevbox.SAMPLES[i];
      html.push("<li><a href='javascript:void(0)' ");
      html.push("onclick='window.orkutdevbox.loadSample(" + i + ")'>")
      html.push(s.name + "</a></li>");
   }
   html.push("</ul>");
   orkutdevbox.getEl('samplelist').innerHTML = html.join('');
};

// Show the snippet preview box for the given snippet index
orkutdevbox.previewSnippet = function(i) {
   if (i < 0) {
      orkutdevbox.getEl('previewbox').style.visibility = 'hidden';
      return;
   }

   orkutdevbox.getEl('previewbox').style.visibility = 'visible';
   orkutdevbox.getEl('previewbox_text').innerHTML = 
                                     orkutdevbox.SNIPPETS[i].code;
};

// Inserts the given snippet (index) into the code at the current
// cursor position
orkutdevbox.insertSnippet = function(i) {
   var start = orkutdevbox.getEl('codebox').selectionStart;
   var end   = orkutdevbox.getEl('codebox').selectionEnd;
   var val   = orkutdevbox.getEl('codebox').value;

   val = val.substring(0, start) + orkutdevbox.SNIPPETS[i].code
       + val.substring(end, val.length);
   end = start + orkutdevbox.SNIPPETS[i].code.length;

   orkutdevbox.getEl('codebox').value = val;
   orkutdevbox.getEl('codebox').selectionEnd = end;

   orkutdevbox.previewSnippet(-1);
};

// Shows code help box that explains to the user what kinds of
// code this application can run
orkutdevbox.onCodeHelp = function() {
   orkutdevbox.getEl('codehelp').style.visibility = 'visible';
};

// Hides the code help box
orkutdevbox.onHideCodeHelp = function() {
   orkutdevbox.getEl('codehelp').style.visibility = 'hidden';
};

// Loads the indicated sample code (by index) into the code tab
orkutdevbox.loadSample = function(i) {
   var code = orkutdevbox.SAMPLES[i].code;
   orkutdevbox.getEl('codebox').value = code;
   orkutdevbox.goToTab('code');
};

// Set up window.orkutdevbox as an alias to orkutdevbox so that
// we can write ugly static event handlers as strings in generated
// code
window.orkutdevbox = orkutdevbox;

// register onLoad as our gadget's onLoad handler
gadgets.util.registerOnLoadHandler(orkutdevbox.onLoad);

// place app name at the appropriate spot
orkutdevbox.getEl('appversion').innerHTML = orkutdevbox.APP_VERSION;

// "debug.say" as an alias to orkutdevbox.say (so client code can call "debug.say")
debug = {};
debug.say = orkutdevbox.say;

